import { levels, LogLevel } from "./log_level";

interface LoggerConfig {
  level: LogLevel;
  enabled: boolean;
}

let G_LOG_CFG: LoggerConfig = {
  level: levels().ALL,
  enabled: true
};
export function Logger_Config(enable: boolean, level: LogLevel) {
  G_LOG_CFG.enabled = enable;
  G_LOG_CFG.level = level;
}

export class BaseLogger {
  moduleName: string = "";
  constructor(moduleName: string) {
    this.moduleName = moduleName;
  }

  /**
   * Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf() (the arguments are all passed to util.format()).
   * @param data
   * @returns {any}
   */
  public debug(...data: any[]): BaseLogger {
    return this.write(levels().DEBUG, data);
  }

  /**
   *
   * @param data
   * @returns {any}
   */
  public info(...data: any[]): BaseLogger {
    return this.write(levels().INFO, data);
  }

  /**
   *
   * @param data
   * @returns {any}
   */
  public warn(...data: any[]): BaseLogger {
    return this.write(levels().WARN, data);
  }

  /**
   * Prints to stderr with newline. Multiple arguments can be passed, with the first used as the primary
   * message and all additional used as substitution values similar to printf() (the arguments are all
   * passed to util.format()).
   * @param data
   * @param args
   * @returns {any}
   */
  public error(...data: any[]): BaseLogger {
    return this.write(levels().ERROR, data);
  }

  public fatal(...data: any[]): BaseLogger {
    return this.write(levels().FATAL, data);
  }

  /**
   *
   * @param data
   * @returns {Logger}
   */
  // public trace(...data: any[]): Logger {
  //   const stack = "\n" + Logger.createStack() + "\n";
  //   data.push(stack);
  //   return this.write(levels().TRACE, data);
  // }

  write(level: LogLevel, data: any[]): BaseLogger {
    if (!G_LOG_CFG.enabled) {
      return this;
    }
    if (!level.isGreaterThanOrEqualTo(G_LOG_CFG.level)) {
      return this;
    }
    var s = "";
    for (var i = 0; i < data.length; i++) {
      if (typeof data[i] !== "string") {
        s += JSON.stringify(data[i]);
      } else {
        s += data[i];
      }
    }
    // console.log(
    //   this.moduleName,
    //   this.formatedLevel(level),
    //   this.startTime(data),
    //   s
    // );
    return this;
  }

  startTime(data: any[]): Date {
    var _startTime = new Date();
    return data && data[0] && data[0].time
      ? data[0].time
      : _startTime.toLocaleDateString();
  }
  public formatedLevel(level: LogLevel): string {
    return (level.toString() + "     ").slice(0, 5);
  }
}

export let logger: BaseLogger = new BaseLogger("default");
